/*
 * directorios.h
 *
 *  Created on: 09/10/2011
 *      Author: Normandia
 *
 *  Funciones para el manejo de directorios y la directory table
 */

#ifndef DIRECTORIOS_H_
#define DIRECTORIOS_H_

#include <stdio.h>
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <dirent.h>
#include <time.h>
#include <sys/types.h>

#include "filesystem.h"
#include "inicializacion.h"
#include "utils.h"
#include "collections/list.h"
#include "collections/queue.h"
#include "log1.h"

//Constantes de tabla de directorio
// Valores posibles de primer byte de campo FileName
#define DT_FILENAME_VALUE_ENTRY 0x00 //Entry is available and no subsequent entry is in use
#define DT_FILENAME_INITIAL_CHR 0x05 //Initial character is actually 0xE5.
#define DT_FILENAME_DOT 0x2E	//0x2E 	'Dot' entry; either '.' or '..'
#define DT_FILENAME_DELETE  0xE5 	// Entry has been previously erased and is available.
					//File undelete utilities must replace this character
					//with a regular character as part of the undeletion process.

// Valores posibles de campo fileAtributes
#define DT_FILEATRIBUTES_READ_ONLY 0x01 //Read Only
#define DT_FILEATRIBUTES_HIDDEN    0x02 //Hidden
#define DT_FILEATRIBUTES_SYSTEM  0x04 	//System
#define DT_FILEATRIBUTES_VOLUME_LABEL 0x08 //Volume Label
#define DT_FILEATRIBUTES_SUBDIRECTORY 0x10 //Subdirectory
#define DT_FILEATRIBUTES_ARCHIVE 0x20 	//Archive
#define DT_FILEATRIBUTES_DEVICE  0x40 	//Device (internal use only, never found on disk)
#define DT_FILEATRIBUTES_UNUSED  0x80 	//Unused
#define DT_FILEATRIBUTES_LONG_FILE 0x0F //designate a long file name entry

#define SIZE_TD 32
#define SIZE_OPENFILE sizeof(OPENFILE)
#define SIZE_LFN 32
#define SIZE_CACHE_TABLE 72

#define SIZE_FILE_NAME 10
#define SIZE_NAME2 12
#define SIZE_NAME3 4

#define VACIO 0
#define LLENO 1

//Rango de valores createdTimeHour
//15‑11 	Hours (0-23)
//10‑5 	Minutes (0-59)
//4‑0 	Seconds/2 (0-29)

//Rango de valores createdDate
//15‑9 	Year (0 = 1980, 127 = 2107)
//8‑5 	Month (1 - 12)
//4‑0 	Day (1 - 31)

typedef struct {
	uint16_t fileName[4];
	uint8_t  fileExt[3];
	uint8_t	 fileAtributes;
	uint8_t	 reserved;
	uint8_t  createdTimeMs;    //fine resolution: 10ms units, values from 0 to 199.
	uint16_t createdTimeHour;  //The hour, minute and second
	uint16_t createdDate;  //The year, month and day
	uint16_t lastAccessDate;
	uint16_t high2Bytes;  //, high 2 bytes of first cluster number in FAT32
	uint16_t lastModifiedTime;
	uint16_t lastModifiedDate;
	uint16_t low2Bytes;  //, high 2 bytes of first cluster number in FAT32
	uint32_t fileSize;  // File size in bytes. Entries with the Volume Label or
			     // Subdirectory flag set should have a size of 0.
}__attribute__((__packed__)) DIRECTORYTABLE;

typedef struct {
	uint8_t	sequenceNumber;
	int16_t fileName[5];
	uint8_t	fileAtributes;
	uint8_t	reserved;
	uint8_t checkSum;
	int16_t Name2[6];
	uint16_t firstCluster;
	int16_t Name3[2];
}__attribute__((__packed__)) DIRECTORYLONGNAME;

typedef struct {
	uint8_t orden;
	uint8_t modificado;
	uint32_t Cluster;
	void * buf;
}__attribute__((__packed__)) T_CACHE;


typedef struct {
	uint16_t Id;
	char    fileName[13];
	char    fileExt[3];
	uint8_t atributos;
	uint32_t primerCluster;
	uint32_t dirCluster;
	uint32_t idTD;
	uint32_t size;
	int16_t vecesAbierto;
	uint8_t modificado;
	T_CACHE cache[16];
}__attribute__((__packed__)) OPENFILE;

//PRIMITIVAS
uint64_t abrirArchivo(const char*);
int leerArchivo(char*, uint64_t fh, size_t size, off_t offset);

//MANEJOS DE DIRECTORIOS
t_list* getDirectoryTable(uint32_t );
t_list* getDirectorioTD(const char *);

OPENFILE * getNodoDirectoryTable(t_list*, char *);
OPENFILE * getArchivoTD(const char*);

//AUXILIARES
uint32_t convertFirstCluster( uint16_t high2Bytes,	uint16_t low2Bytes);

int set_getattr(struct stat *st,const char *path);

int closureDirectoryTable (void*);
void destroyList(t_list*);
uint32_t convertFilesize( uint32_t fileSize);
mode_t convertir_modo(uint8_t attr);

OPENFILE* archivoAbierto(uint64_t fh);

char *armaConExt(char*,uint8_t*);

void arreglar_fucking_string(char* str, size_t tamanio);

void *leerClusterEnCache(uint64_t fh ,uint32_t n_cluster);
void agregarCache(void *buffer,uint64_t fh, uint32_t n_cluster);
void cache_pasarAprimero(OPENFILE *file, int index);

void dump_cache(int);

t_list* listOpenFile;

#endif /* DIRECTORIOS_H_ */
